'''
Created on 29/09/2012

@author: Christian
'''


from Repository import Repository
from git.repo.base import Repo
from git.db import GitCmdObjectDB


class RepositoryGIT(Repository):
    
    def __init__(self, path, projectname):        
        super(RepositoryGIT, self).__init__(path, projectname, 'GIT') 

    def connect(self):
        self._repo = Repo(self.path, odbt=GitCmdObjectDB)

    def getChangesAndFiles(self, changeid, repoid, fromrev, torev):
        print "Preparing changes from %s to %s" % (fromrev, torev)
        
        changes = []
        files = []
        counter = fromrev
        changelog = self._getChangeLog()

        if torev > len(changelog):
            torev = len(changelog)
        
        for rev in range(fromrev, torev):
            commit = changelog[rev]
            # for commit in changelog:
            print "Processing change %s/%s" % (rev, self.getSize())
            
            changeobj = self._processChange(commit, changeid, repoid)
            changes.append(changeobj)
            
            if len(commit.parents) != 2:
                files.extend(self._processChangeFiles(commit, changeid))
                
            changeid += 1
            counter += 1
        
        return (changes, files)


    def _processChange(self, commit, changeid, repoid):
        
        parentA = ''
        parentB = ''
        
        if len(commit.parents) == 1:
            parentA = commit.parents[0].hexsha
        if len(commit.parents) == 2:
            parentA = commit.parents[0].hexsha
            parentB = commit.parents[1].hexsha

        if len(commit.parents) == 2:
            merge = 1
        else:
            merge = 0

	if commit.author.name:
		name = self._removeNonAscii(commit.author.name).encode('utf-8')
	else:
		name = ''

	if commit.author.email:
		email = self._removeNonAscii(commit.author.email).encode('utf-8')
	else:
		email = ''

        change = [changeid,
                  '',  # GIT has no revision numbers
                  commit.hexsha,
                  name,
                  email,
                  commit.committed_date,
                  commit.committed_date,
                  parentA,
                  parentB,
                  merge,
                  self._removeNonAscii(commit.message).encode('utf-8'),
                  str(repoid)]
        
        return change       


    def _processChangeFiles(self, commit, changeid):
        files = []       
        
        # Domain: 'E'dit, 'A'dd, 'R'emove, 'D'elete, 'U'nknown, 'I'gnore, 'C'lean
        modification = ''
        filename = ''
        
        if not commit.parents:
            diffs = self._changelog[-1].diff(commit.hexsha)
            modification = 'A'
            for diff_added in diffs.iter_change_type('A'):
                filename = diff_added.b_blob.path
                files.append(self._createFile(filename, modification, changeid))
            for diff_added in diffs.iter_change_type('M'):
                filename = diff_added.b_blob.path
                files.append(self._createFile(filename, modification, changeid))
        else:
            for parent in commit.parents:
                diffs = parent.diff(commit.hexsha)
                
                for diff_added in diffs.iter_change_type('A'):
                    modification = 'A'
                    filename = diff_added.b_blob.path
                    files.append(self._createFile(filename, modification, changeid))
                
                for diff_removed in diffs.iter_change_type('D'):
                    modification = 'R'
                    filename = diff_removed.a_blob.path
                    files.append(self._createFile(filename, modification, changeid))
    
                for diff_modified in diffs.iter_change_type('M'):
                    modification = 'E'
                    filename = diff_modified.a_blob.path
                    files.append(self._createFile(filename, modification, changeid))
                   
                for diff_renamed in diffs.iter_change_type('R'):  
                    modification = 'A'
                    filename = diff_renamed.rename_from
                    files.append(self._createFile(filename, modification, changeid))  
                    modification = 'R'
                    filename = diff_renamed.rename_to
                    files.append(self._createFile(filename, modification, changeid))
        
        return files

    def _createFile(self, filename, modification, changeid):
        extension = self._extractFileExtension(filename)
        filechanged = [filename,
                       extension,
                       modification,
                       changeid]
        return filechanged
    
    def getSize(self):
        if not self._size:
            self._size = len(self._getChangeLog())
        return self._size
    
    def _getChangeLog(self):
        if not self._changelog:
            self._changelog = list(self._repo.iter_commits())
            self._changelog.reverse()
        return self._changelog

    def _removeNonAscii(self, s): 
	return "".join(i for i in s if ord(i)<128)

    
